#include "meshType.h"
#include "tetgenParser.h"
#include <iostream>
#include <sstream>
using namespace std;

int main(int argc, char* argv[])
{
	std::vector<MeshUtils::Vector3> nodes;
	std::vector<MeshUtils::Element> elements;
	unsigned int nbNodes;
	unsigned int nbElts;
	double scale = 1.0;
	if(argc != 3)
	{
		cout << "usage : "  << argv[0] << " file.tet scale" << endl;
		exit(0);
	}
	
	scale = atof(argv[2]);

	MeshUtils::TetgenParser parser ( argv[1] );
	parser.load ( nodes, elements, nbNodes, nbElts );
	
	unsigned int nIdx = 0;
	for(std::vector<MeshUtils::Vector3>::iterator nIt = nodes.begin() ; nIt != nodes.end() ; nIt++)
	{
		cout << "#declare X" << nIdx++ << " = <" << nIt->x*scale << ", " << nIt->y*scale << ", " << nIt->z*scale << ">;" << endl;
	}

	unsigned int tIdx = 0;
	std::vector<unsigned int> toRefine;
	for(std::vector<MeshUtils::Element>::iterator eIt = elements.begin() ; eIt != elements.end() ; eIt++)
	{
		stringstream ss;
		MeshUtils::Vector3 avg;avg.x = 0 ; avg.y = 0; avg.z = 0;
		bool hasX28 = false;
		bool hasX0 = false;
		for(std::vector<unsigned int>::iterator nIt = eIt->nodesList.begin() ; nIt != eIt->nodesList.end() ; nIt++)
		{
			if(*nIt == 28)
				hasX28 = true;
			if(*nIt == 0)
				hasX0 = true;
			if(*nIt != 28)
				avg = avg + nodes[*nIt];
		}
		
		if(hasX0 && hasX28)
			toRefine.push_back(tIdx);
		
		tIdx++;
		avg = (avg * (1.0/3.0) - nodes[28]) * scale;

		
		
		ss << "X" << eIt->nodesList[0]
			<< ", X" << eIt->nodesList[1]
			<< ", X" << eIt->nodesList[2]
			<< ", X" << eIt->nodesList[3];
		cout << "object{ Tetrahedron_by_Corners(" << ss.str() << ", Rl, Rp, 0) pigment{ color rgb<1.0,1,0> }}" << endl;
		stringstream ss2;
		ss2 << "X" << eIt->nodesList[0] << "/" << avg.norm()
			<< ", X" << eIt->nodesList[1]<< "/" << avg.norm()
			<< ", X" << eIt->nodesList[2]<< "/" << avg.norm()
			<< ", X" << eIt->nodesList[3]<< "/" << avg.norm();
		
		//cout << "object{ Tetrahedron_by_Corners(" << ss2.str() << ", 0,  0, 1) pigment{ gradient <" 
		//<< avg.x << ", " << avg.y << ", " << avg.z << "> color_map { [0 color rgbt <0.0,1.0,0.0, 0.85>] [1.0 //color rgbt <1.0,1.0,1.0, 0.65>]}} scale "<< avg.norm() << " }" << endl;
		
		cout << "object{ Vector( 0,<" << avg.x << ", " << avg.y << ", " << avg.z << ">, Rl) pigment{ color rgb<1,0,0> }  }" << endl;

		cout << "sphere {(X" << eIt->nodesList[0] <<"+ X" << eIt->nodesList[1]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;;
		cout << "sphere {(X" << eIt->nodesList[0] <<"+ X" << eIt->nodesList[2]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;
		cout << "sphere {(X" << eIt->nodesList[0] <<"+ X" << eIt->nodesList[3]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;
		cout << "sphere {(X" << eIt->nodesList[1] <<"+ X" << eIt->nodesList[2]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;
		cout << "sphere {(X" << eIt->nodesList[1] <<"+ X" << eIt->nodesList[3]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;
		cout << "sphere {(X" << eIt->nodesList[2] <<"+ X" << eIt->nodesList[3]<< ") / 2, 0.08 pigment{color rgb<0,1,0>}}" << endl;
		
		
	}
	for(std::vector<unsigned int>::iterator eIt = toRefine.begin() ; eIt != toRefine.end() ; eIt++)
	{
		stringstream X0; X0 << "X" << elements[*eIt].nodesList[0];
		stringstream X1; X1 << "X" << elements[*eIt].nodesList[1];
		stringstream X2; X2 << "X" << elements[*eIt].nodesList[2];
		stringstream X3; X3 << "X" << elements[*eIt].nodesList[3];

		stringstream X4; X4 << "(" << X0.str() << " + " << X1.str() << ")/2" ;
		stringstream X5; X5 << "(" << X1.str() << " + " << X2.str() << ")/2";
		stringstream X6; X6 << "(" << X2.str() << " + " << X3.str() << ")/2";
		stringstream X7; X7 << "(" << X3.str() << " + " << X0.str() << ")/2";
		stringstream X8; X8 << "(" << X1.str() << " + " << X3.str() << ")/2";
		stringstream X9; X9 << "(" << X0.str() << " + " << X2.str() << ")/2";

		stringstream t0; t0 << X0.str() << ", "
			<< X4.str() << ", "
			<< X9.str() << ", "
			<< X7.str();
			
		stringstream t1; t1 << X1.str() << ", "
			<< X4.str() << ", "
			<< X5.str() << ", "
			<< X8.str();
			
		stringstream t2; t2 << X2.str() << ", "
			<< X6.str() << ", "
			<< X5.str() << ", "
			<< X9.str();
			
		stringstream t3; t3 << X3.str() << ", "
			<< X7.str() << ", "
			<< X8.str() << ", "
			<< X6.str();
			
		stringstream t4; t4 << X7.str() << ", "
			<< X4.str() << ", "
			<< X8.str() << ", "
			<< X9.str();
			
		stringstream t5; t5 << X4.str() << ", "
			<< X5.str() << ", "
			<< X8.str() << ", "
			<< X9.str();
		stringstream t6; t6 << X8.str() << ", "
			<< X9.str() << ", "
			<< X5.str() << ", "
			<< X6.str();
		stringstream t7; t7 << X7.str() << ", "
			<< X6.str() << ", "
			<< X8.str() << ", "
			<< X9.str();

		cout << "object{ Tetrahedron_by_Corners(" << t0.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t1.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t2.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t3.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t4.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t5.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t6.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		cout << "object{ Tetrahedron_by_Corners(" << t7.str() << ", Rl, Rp, 0) pigment{ color rgb<0.0,1,0> }}" << endl;
		
		//cout << "object{ Vector( 0,<" << avg.x << ", " << avg.y << ", " << avg.z << ">, Rl) pigment{ color rgb<1,0,0> }  }" << endl;
		
	}
	return 1;
}